#!/usr/bin/env ruby

require 'optparse'
require "readline"

class GenConf
  def initialize
    @listfile = nil
    @outfile  = nil
    @protocol = nil
    @storages = nil
  end

  def interactive
    stty_save = `stty -g`.chomp
    begin
      unless @listfile
        Readline.completion_proc = Readline::FILENAME_COMPLETION_PROC
        puts "step1. select a file which contains your cluster node list:"
        @listfile = Readline.readline("> ", true).strip
      end

      unless @outfile
        puts "step2. enter a filename which will be written as output:"
        @outfile = Readline.readline("> ", true).strip
      end

      unless @procotol
        Readline.completion_proc = proc {|word|
          %w[aistsss tokyotyrant memcachedb].grep(/\A#{Regexp.quote word}/)
        }
        puts "step3. select which protocol you use:"
        @protocol = Readline.readline("> ", true).strip
      end

      unless @storages
        puts "step4. number of storage engine per node:"
        @storages = Readline.readline("> ", true).strip.to_i
      end
    rescue Interrupt
      system("stty", stty_save)
      exit
    end
  end

  def check_args
    ARGV.options do |opts|
      opts.on("-o", "--output file", "set output filename") do |outfile|
        @outfile = outfile
      end
      opts.on("-l", "--list file", "cluster node list") do |listfile|
        @listfile = listfile
      end
      opts.on("-p", "--protocol protocol", "data access protocol") do |protocol|
        @protocol = protocol
      end
      opts.on("-s", "--storages num", "number of storage engine") do |storages|
        @storages = storages.to_i
      end
      opts.parse!
    end

    if @outfile.nil? or @listfile.nil? or @protocol.nil? or @storages.nil?
      interactive
    end

    self
  end

  def add_storage_entry(out, node)
    portbase = 21201
    out.puts "    <!-- storage daemon socket address and protocol -->"
      @storages.times do |i|
        out.puts <<EOS
    <storage>
      <protocol>#{@protocol}</protocol>
      <host>#{node}</host>
      <port>#{portbase + i}</port>
    </storage>
EOS
    end
  end

  def add_rmi_entries(out, list)
    out.puts "  <!-- java rmi socket address -->"
    list.each do |p|
      out.puts <<EOS
  <worker>
    <host>#{p}</host>
    <port>12345</port>
EOS
      add_storage_entry(out, p)
      out.puts("  </worker>")
    end
  end


  def write(out=@outfile)
    f = File::open(out, "w")
    f.puts '<cluster>'
    f.puts

    peerlist = %x{ egrep -v '(^$|^[ \t]*#.*$)' #{@listfile} }.split
    self.add_rmi_entries(f, peerlist)

    f.puts '</cluster>'
    f.close
  end
end

GenConf.new.check_args.write
